#include <ximera/net/socket.hpp>
#include <ximera/threading/thread.hpp>
#include <ximera/logger.hpp>
#include <iostream>

using namespace ximera;

void serverThread(threading::Thread::ShouldExitFunction const& shouldExit)
{
    net::Socket socket;
    socket.bind(net::IPEndPoint(net::IPAddress::any, 1234));
    socket.listen();

    XIMERA_LOG() << "Listening...\n";

    net::Socket client;
    socket.accept(client);

    XIMERA_LOG() << "Client connected\n";

    char data[] = "Idiot!\r\n";
    XIMERA_LOG() << "Sending (" << sizeof(data) << "): \n" << data << std::endl;

    UInt32 sent = client.send(data, sizeof(data));

    XIMERA_LOG() << "Sent (" << sent << ")\n";

    UInt32 const bufsize = 1024;
    char buffer[bufsize];
    UInt32 recvd = client.receive(buffer, bufsize);

    XIMERA_LOG() << "Received (" << recvd << ") : \n" << std::wstring(buffer, buffer + recvd) << std::endl; 
}

int main()
{
    try
    {
        XIMERA_LOG().stream(&std::wcout);

        {
            // Client test

            XIMERA_LOG() << "Testing Socket Client\n";

            net::Socket socket;
            socket.connect(net::IPEndPoint(L"google.com", 80));
            //socket.blocking(false);

            char data[] = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
            XIMERA_LOG() << "Sending (" << sizeof(data) << "): \n" << data << std::endl;

            UInt32 sent = socket.send(data, sizeof(data));

            XIMERA_LOG() << "Sent (" << sent << ")\n";

            while (!socket.available())
            {
                XIMERA_LOG() << "Nothing yet, waiting...\n";
                threading::Thread::sleep(100);
            }

            UInt32 const bufsize = 1024;
            char buffer[bufsize];
            UInt32 recvd = socket.receive(buffer, bufsize);
            
            XIMERA_LOG() << "Received (" << recvd << ") : \n" << std::wstring(buffer, buffer + recvd) << std::endl; 
        }

        {
            // Server test

            XIMERA_LOG() << "Testing Socket Server\n";

            threading::Thread server(&serverThread);
            server.start();

            threading::Thread::sleep(100);

            net::Socket socket;
            socket.connect(net::IPEndPoint(L"localhost", 1234));            

            UInt32 const bufsize = 1024;
            char buffer[bufsize];
            UInt32 recvd = socket.receive(buffer, bufsize);

            XIMERA_LOG() << "Received (" << recvd << ") : \n" << std::wstring(buffer, buffer + recvd) << std::endl; 

            char data[] = "GET / HTTP/1.1\r\nHost: www.google.com\r\nConnection: close\r\n\r\n";
            XIMERA_LOG() << "Sending (" << sizeof(data) << "): \n" << data << std::endl;

            UInt32 sent = socket.send(data, sizeof(data));

            XIMERA_LOG() << "Sent (" << sent << ")\n";
        }
    }
    catch (ximera::Exception& e)
    {
        XIMERA_LOG() << e << std::endl;
    }
}
